package Query;


import java.util.ArrayList;
import java.util.List;
import java.util.Set;

//Result indica que espero que me devuelva el query, debe ser definido 
//obligatoriamente en la declaracin de las subclases de Query
public abstract class Query<T, Result> {

	private List<T> elements = new ArrayList<T>();
	private QueryFiltro<T>filtro;
	protected ArrayList<T> elementsPostFiltro;
	protected Result result;
	
	public Query( List<T> elementos,QueryFiltro<T>filtro ){
		this.setElements(elementos);
		this.setFiltro(filtro);
	}
	
	public Query(Set<T> elementos,
			QueryFiltro<T> filtro) {
		this.setFiltro(filtro);
		this.setElements(elementos);
	
		
	}

	public void execute(){
		elementsPostFiltro = new ArrayList<T>();
		for(T element : elements){
			if(getFiltro().evaluate(element)){
				elementsPostFiltro.add(element);
			}
		}
		this.proccesResult();
		
	}
	
	protected abstract void proccesResult();

	public Result getResult(){
		return result;
	}

	public void setElements(List<T>elements2) {
		//No quiero que lo que me seteen me lo puedan moificar desde afuera ya que list es mutable.
		this.clear();
		elements.addAll(elements2);
	}
	
	private void setElements(Set<T> elementos) {
		this.clear();
		for(T o : elementos) elements.add(o); 
		
	}

	private void clear() {
		elements.clear();
	}

	public void setFiltro(QueryFiltro<T> filtro) {
		this.filtro = filtro;
	}


	public QueryFiltro<T> getFiltro() {
		return filtro;
	}
	
}
